package vben.core.module.mon.log.oper;

import cn.hutool.extra.servlet.ServletUtil;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.OperatingSystem;
import eu.bitwalker.useragentutils.UserAgent;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import vben.core.module.mon.log.error.MonLogError;
import vben.core.module.mon.log.error.MonLogErrorService;
import vben.core.common.utils.web.XuserUtil;

import javax.servlet.http.HttpServletRequest;

@Component
@Aspect
@Slf4j
public class OplogAspect {

    private final MonLogOperService operLogService;
    private final MonLogErrorService errorLogService;

    ThreadLocal<Long> currentTime = new ThreadLocal<>();

    public OplogAspect(MonLogOperService operLogService,
                       MonLogErrorService errorLogService) {
        this.operLogService = operLogService;
        this.errorLogService = errorLogService;
    }

    /**
     * 配置切入点
     */
    @Pointcut("@annotation(vben.core.module.mon.log.oper.Oplog)")
    public void logPointcut() {
        // 该方法无方法体,主要为了让同类中其他方法使用此切入点
    }

    /**
     * 配置环绕通知,使用在方法logPointcut()上注册的切入点
     *
     * @param joinPoint join point for advice
     */
    @Around("logPointcut()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result;
        currentTime.set(System.currentTimeMillis());
        result = joinPoint.proceed();
        MonLogOper log = new MonLogOper("INFO",System.currentTimeMillis() - currentTime.get());
        currentTime.remove();
        HttpServletRequest request = RequestHolder.getHttpServletRequest();
        String ip= ServletUtil.getClientIP(request);
        String agent = request.getHeader("User-Agent");
        UserAgent userAgent = UserAgent.parseUserAgentString(agent);
        Browser browser = userAgent.getBrowser();
        OperatingSystem os = userAgent.getOperatingSystem();
//        logService.save(getUsername(), XstrUtil.getBrowser(request), XstrUtil.getIp(request),joinPoint, log);
        operLogService.save(getUsername(),os.toString(), browser.getName(), ip,joinPoint, log);
        return result;
    }

    /**
     * 配置异常通知
     *
     * @param joinPoint join point for advice
     * @param e exception
     */
    @AfterThrowing(pointcut = "logPointcut()", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
        MonLogError log = new MonLogError("ERROR",System.currentTimeMillis() - currentTime.get());
        currentTime.remove();
        log.setError(ThrowableUtil.getStackTrace(e));
        HttpServletRequest request = RequestHolder.getHttpServletRequest();
        String ip= ServletUtil.getClientIP(request);
        String agent = request.getHeader("User-Agent");
        UserAgent userAgent = UserAgent.parseUserAgentString(agent);
        Browser browser = userAgent.getBrowser();
        OperatingSystem os = userAgent.getOperatingSystem();
//        logService.save(getUsername(), XstrUtil.getBrowser(request), XstrUtil.getIp(request), (ProceedingJoinPoint)joinPoint, log);
        errorLogService.save(getUsername(),os.toString(), browser.toString(), ip, (ProceedingJoinPoint)joinPoint, log);
    }

    public String getUsername() {
        try {
            return XuserUtil.getUserId();
        }catch (Exception e){
            return "";
        }
    }
}
